///////////////////////////////////////////////////////////////////////////////
// Company: University of Cincinnati
// Author: Jordan Ross, Ben Gentry, Bryan Butsch
//
// Created Date: 09/22/2013
// Design Name:
// Module Name: top_level
// Project Name: top_level
// Target Devices: Cyclone II EP2C20F484C7
// Tool Versions: Quartus 13.0
// Description: This module instantiates a bare processor, a memory unit, and
//    a counter to cycle through memory addresses.
// 
// Dependencies: proc.v
//               memory.v
//               counter.v
// 
// Revision:
// 0.01 - File Created
//
// Additional Comments:
//
///////////////////////////////////////////////////////////////////////////////
module top_level #(parameter width=9)(
    input Clock,            // Clock
    input Resetn,           // Reset Signal
    input Run,              // Run Signal
    input [width-1:0]SW,    // DE-1 Board switches
    output Done,            // Done Signal from processor
    output [width-1:0]LEDR, // 9-bit LED output
    output [6:0]HEX0,       // Seg0 Output port
    output [6:0]HEX1,       // Seg1 Output port
    output [6:0]HEX2,       // Seg2 Output port
    output [6:0]HEX3        // Seg3 Output port
);
    
    /* Internal wire connections */
    wire [width-1:0] DIN;      // Data wire from mux to processor
    wire [width-1:0] DIN_MEM;  // Data wire from memory to mux
    wire [width-1:0] DIN_PN;   // Data wire from port_n to mux
    wire [width-1:0] Data;     // Data wire from processor to memory
    wire [width-1:0] Addr;     // Address wire from processor to memory
    wire Write;                // Write Signal from processor
    wire E;                    // Enable Signal for LEDs
    wire A7, A8;               // upper two bits of ADDR
    
    // Assign the MSB address bits as A7 & A8
    assign A7 = Addr[7];
    assign A8 = Addr[8];
    
    /* Internal logic */
    wire wr_en, nor1Out, nor2Out;
    nor nor1(nor1Out, A7, A8);
    nor nor2(nor2Out, ~A7, A8);
    and and1(wr_en, Write, nor1Out);
    and and2(E, nor2Out, Write);
    
    /* Instantiate the memory module */
    memory mem(
        .address    (Addr[6:0]),
        .data       (Data),
        .wren       (wr_en),
        .clock      (Clock),
        .q          (DIN_MEM)
    );
    
    /* Instantiate the processor module */
    Proc processor(
        .DIN    (DIN),
        .Resetn (Resetn),
        .Clock  (Clock),
        .Run    (Run),
        .Done   (Done),
        .W      (Write),
        .DOUT   (Data),
        .ADDR   (Addr),
        .Seg0   (HEX0),
        .Seg1   (HEX1),
        .Seg2   (HEX2),
        .Seg3   (HEX3)
    );
    
    /* Output LED logic */
    led led(
        .Clock  (Clock),
        .E      (E),
        .Data   (Data),
        .Q      (LEDR)
    );
    
    /* Instantiate port_n Register */
    port_n port_n(
        .Switches(SW),
        .Clock(Clock),
        .Q(DIN_PN)
    );
    
    /* Instantiate DIN_mux */
    DIN_mux DIN_mux(
        .DIN_MEM(DIN_MEM),
        .DIN_PN(DIN_PN),
        .A8(A8),
        .DIN(DIN)
    );    
    
endmodule

